<template>
  <div class="app-container">
    <div id="cesiumApp" class="cesium-container fullSize"></div>
    <div v-if="isViewer" class="layout-container">
      <Layout />
    </div>
    <div class="left-btn-con" @click="handleBtnClick">
      <transition mode="out-in" name="img-change">
        <img v-if="!isOpen" :src="leftImg" alt="" key="open" />
        <img v-else :src="rightImg" alt="" key="no-open" />
      </transition>
    </div>
    <div class="right-btn-con" @click="handleBtnClick">
      <transition mode="out-in" name="img-change">
        <img v-if="!isOpen" :src="rightImg" alt="" key="open" />
        <img v-else :src="leftImg" alt="" key="no-open" />
      </transition>
    </div>
  </div>
</template>

<script>
import Layout from '../../components/layout/layout.vue'
import { loadOneMapData } from '@/api/app/app.js'
import leftImg from '@/assets/main/收起.png'
import rightImg from '@/assets/main/展开.png'
export default {
  data () {
    this.leftImg = leftImg
    this.rightImg = rightImg
    return {
      isViewer: false,
      isOpen: false
    }
  },
  mounted () {
    this.initViewer()
  },
  provide () {
    return {
      getViewer: this.getViewer,
      handleHtmlLabelShow: this.handleHtmlLabelShow,
      handleAreaData: this.handleAreaData,
      removeGrid: this.removeGrid,
      handleModelDisplay: this.handleModelDisplay
    }
  },
  components: {
    Layout
  },
  watch: {
    $route: function (newRoute) {
      this.isOpen = newRoute.meta.isOpen
    }
  },
  methods: {
    handleBtnClick () {
      if (!this.$route.meta.canOpen) return
      if (!this.isOpen) return this.$router.push({ name: 'roadPlan' })
      this.$router.back()
    },
    getViewer () {
      return this.viewer
    },
    initViewer () {
      const global06 = new Cesium.TileMapServiceImageryProvider({
        url:
          'http://58.49.74.231:114/web_bridge/static/mapService/google-L1-L7-WEBM-TMS/',
        fileExtension: 'jpg',
        credit: 'global06'
      })

      const viewer = new Cesium.Viewer('cesiumApp', {
        animation: false,
        baseLayerPicker: false,
        fullscreenButton: true,
        vrButton: false,
        homeButton: false,
        sceneModePicker: false,
        timeline: false,
        navigationHelpButton: false,
        geocoder: false,
        imageryProvider: global06
      })

      viewer._cesiumWidget._creditContainer.style.display = 'none' // 隐藏版权信息
      viewer.scene.globe.depthTestAgainstTerrain = true
      viewer.scene.moon.show = false // 隐藏月球
      viewer.screenSpaceEventHandler.removeInputAction(
        Cesium.ScreenSpaceEventType.LEFT_CLICK
      )

      viewer.camera.setView({
        destination: {
          x: -2708503.6493737716,
          y: 4696835.512897571,
          z: 3364147.189160538
        },
        orientation: {
          heading: 6.283185303233039,
          pitch: -1.5707102676362559,
          roll: 0
        }
      })

      window.viewer = this.viewer = viewer
      this.isViewer = true

      this.loadOneData()
      this.initModel()
    },
    handleModelDisplay (arr) {
      console.log(arr)
      this.modelList.forEach((el) => (this[el].show = false))
      arr.forEach((item) => {
        this[item].show = true
      })
    },
    // 加载BIM模型
    initModel () {
      this.modelList = []
      const viewer = this.getViewer()
      // 主桥
      this.zhuqiaoTileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data22/zhuqiao/tileset.json'
      })
      this.zhuqiaoTileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.9536986906263,
          31.99376382402195,
          -360
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(0))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.zhuqiaoTileset._root.transform = m

        viewer.scene.primitives.add(this.zhuqiaoTileset)
        this.zhuqiaoTileset.show = false

        this.modelList.push('zhuqiaoTileset')
      })
      // 项目部
      this.xmbTileset = new Cesium.Cesium3DTileset({
        url: 'http://58.49.74.231:114/sandTable_changtai/data/xmb/tileset.json'
        // maximumScreenSpaceError: 64,
        // maximumMemoryUsage: 512
      })
      this.xmbTileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.97070423507648,
          31.993185135508455,
          -0.9618767919927972
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(-134.7))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.xmbTileset._root.transform = m

        viewer.scene.primitives.add(this.xmbTileset)
        this.xmbTileset.show = false

        this.modelList.push('xmbTileset')
      })
      // 项目部-不带顶
      this.xiangmbTileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data/xiangmb/tileset.json'
      })
      this.xiangmbTileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.97070423507648,
          31.993185135508455,
          -0.9618767919927972
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(-134.7))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.xiangmbTileset._root.transform = m

        viewer.scene.primitives.add(this.xiangmbTileset)
        this.xiangmbTileset.show = false

        this.modelList.push('xiangmbTileset')
      })
      // 陆上拌和站
      this.lsbhzTileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data/lsbhz/tileset.json'
      })
      this.lsbhzTileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.95502450642816,
          31.983010406386164,
          -1
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(
          Cesium.Math.toRadians(-75.39999999999999)
        )
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.lsbhzTileset._root.transform = m

        viewer.scene.primitives.add(this.lsbhzTileset)
        this.lsbhzTileset.show = false

        this.modelList.push('lsbhzTileset')
      })
      // 栈桥
      this.zhanqiaoTileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data/zhanqiao/tileset.json'
      })
      this.zhanqiaoTileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.96311843577062,
          32.00305737035829,
          -15.161896071803907
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(-133.8))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.zhanqiaoTileset._root.transform = m

        viewer.scene.primitives.add(this.zhanqiaoTileset)
        this.zhanqiaoTileset.show = false

        this.modelList.push('zhanqiaoTileset')
      })
      // 栈桥倾斜摄影
      // this.zhanqiaoQingXieTileset = new Cesium.Cesium3DTileset({
      //   url:
      //     'http://58.49.74.231:114/sandTable_changtai/data/qingxie/zhanqiao/tileset.json'
      // })
      // this.zhanqiaoQingXieTileset.readyPromise.then(() => {
      //   const offset = Cesium.Cartesian3.fromDegrees(
      //     119.96053647478348,
      //     32.00180207497795,
      //     -26.42072856106802
      //   )
      //   const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
      //   const m = new Cesium.Matrix4.fromArray(aaa)
      //   const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(0))
      //   Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
      //   this.zhanqiaoQingXieTileset._root.transform = m

      //   viewer.scene.primitives.add(this.zhanqiaoQingXieTileset)
      //   this.zhanqiaoQingXieTileset.show = false

      //   this.modelList.push('zhanqiaoQingXieTileset')
      // })
      // 8#墩提升栈
      this.tishengzhan8Tileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data22/8tishengzhan_tiles/tileset.json'
      })
      this.tishengzhan8Tileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.95911886335041,
          32.00091099757464,
          -10.735856174264013
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(42.900000000000034))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.tishengzhan8Tileset._root.transform = m

        viewer.scene.primitives.add(this.tishengzhan8Tileset)
        this.tishengzhan8Tileset.show = false

        this.modelList.push('tishengzhan8Tileset')
      })

      // 14#墩提升栈
      this.tishengzhan14Tileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data22/14tishengzhang_tiles/tileset.json'
      })
      this.tishengzhan14Tileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.95033660086044,
          31.99392884040164,
          -9.19086389356103
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(-135.10000000000002))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.tishengzhan14Tileset._root.transform = m

        viewer.scene.primitives.add(this.tishengzhan14Tileset)
        this.tishengzhan14Tileset.show = false

        this.modelList.push('tishengzhan14Tileset')
      })

      // 料石码头
      this.liaoshiTileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data22/liaoshimatou/tileset.json'
      })
      this.liaoshiTileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.96448528119708,
          31.983373489915824,
          -15
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(-118.39999999999995))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.liaoshiTileset._root.transform = m

        viewer.scene.primitives.add(this.liaoshiTileset)
        this.liaoshiTileset.show = false

        this.modelList.push('liaoshiTileset')
      })

      // 沉井平台
      this.cjptTileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data22/chengjingpingtai/tileset.json'
      })
      this.cjptTileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.96353627951524,
          32.00518250619489,
          12.146028237943344
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(-43.399999999999984))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.cjptTileset._root.transform = m

        viewer.scene.primitives.add(this.cjptTileset)
        this.cjptTileset.show = false

        this.modelList.push('cjptTileset')
      })

      // 13#码头
      this.matou13Tileset = new Cesium.Cesium3DTileset({
        url:
          'http://58.49.74.231:114/sandTable_changtai/data22/13matou-tiles/tileset.json'
      })
      this.matou13Tileset.readyPromise.then(() => {
        const offset = Cesium.Cartesian3.fromDegrees(
          119.95214541245925,
          31.99558604244544,
          -32.05281253691885
        )
        const aaa = new Cesium.Transforms.eastNorthUpToFixedFrame(offset)
        const m = new Cesium.Matrix4.fromArray(aaa)
        const m1 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(-44.99999999999999))
        Cesium.Matrix4.multiplyByMatrix3(m, m1, m)
        this.matou13Tileset._root.transform = m

        viewer.scene.primitives.add(this.matou13Tileset)
        this.matou13Tileset.show = false

        this.modelList.push('matou13Tileset')
      })
    },
    loadOneData () {
      loadOneMapData().then((res) => {
        const data = res.data
        if (data.message !== 'SUCCESS') return
        const objectsData = JSON.parse(data.data.sceneContent).folderData[0]
          .ObjectsData
        const pointArr = []
        this.areaArr = []
        let i = 0
        while (i < objectsData.length) {
          const obj = objectsData[i]
          if (obj.type === 'PointObject') pointArr.push(obj.PointData[0])
          if (obj.type === 'AreaMarker') { this.areaArr.push(obj.AreaObjectData[0].AreaGraphicData[0]) }
          i++
        }
        this.handlePointData(pointArr)
        // this.handleAreaData(areaArr)
      })
    },
    handleAreaData () {
      // console.log(list)
      const czml = [
        {
          id: 'document',
          name: 'CZML Geometries: Polygon',
          version: '1.0'
        }
      ]
      this.areaArr.forEach((item, index) => {
        czml.push({
          id: item.ID,
          name: '网格' + index,
          polygon: {
            positions: {
              cartographicDegrees: this.mapArray(item.Positions)
            },
            material: {
              solidColor: {
                color: {
                  rgba: [
                    item.AreaColor[0],
                    item.AreaColor[1],
                    item.AreaColor[2],
                    // Math.floor(item.AreaColor[3] * 255)
                    100
                  ]
                }
              }
            }
          }
        })
      })
      this.dataSourcePromise = Cesium.CzmlDataSource.load(czml)
      this.viewer.dataSources.add(this.dataSourcePromise)
    },
    removeGrid () {
      this.viewer.dataSources.removeAll()
    },
    mapArray (arr) {
      const array = []
      arr.forEach((item) => {
        array.push(item.lng, item.lat, item.h)
      })
      return array
    },
    handlePointData (list) {
      this.els = []
      list.forEach((item) => {
        const { type } = item.MessageProperty.Json

        const div = document.createElement('div')
        div.classList.add('label-con')
        div.labelPosition = item.Positions
        div.messageText = item.Text
        div.params = item

        const text = document.createElement('p')
        text.classList.add('label-text' + type)
        text.innerHTML = item.Text
        text.messageText = item.Text
        text.params = item

        const div2 = document.createElement('div')
        div2.messageText = item.Text
        div2.params = item

        const img = document.createElement('img')
        img.src = item.BillboardImgSrc
        img.messageText = item.Text
        img.params = item
        const span = document.createElement('span')
        span.params = item

        div2.appendChild(img)
        div2.appendChild(span)

        div.appendChild(text)
        div.appendChild(div2)
        div.messageType = type

        this.els.push(div)
        this.viewer.container.appendChild(div)
      })
      this.viewer.scene.preRender.addEventListener(() => {
        this.updateEls()
      })

      this.cesiumHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)

      this.cesiumHandler.setInputAction(() => {
        this.findCollision()
      }, Cesium.ScreenSpaceEventType.LEFT_UP)

      this.cesiumHandler.setInputAction(() => {
        this.findCollision()
      }, Cesium.ScreenSpaceEventType.RIGHT_UP)

      this.cesiumHandler.setInputAction(this.debounce(this.findCollision, 100), Cesium.ScreenSpaceEventType.WHEEL)

      this.cesiumHandler.setInputAction(() => {
        this.findCollision()
      }, Cesium.ScreenSpaceEventType.MIDDLE_UP)
    },
    debounce (func, wait) {
      let timer
      const context = this
      const args = arguments
      return function () {
        if (timer) clearTimeout(timer)

        timer = setTimeout(() => {
          func.apply(context, args)
        }, wait)
      }
    },
    findCollision () {
      const len = this.els.length
      const array = new Array(len)

      for (let i = 0; i < len; i++) {
        if (this.els[i].shouldShow) {
          this.els[i].style.display = ''
        }
        array[i] = []
      }

      for (let i = 0; i < len; i++) {
        const el = this.els[i]
        if (!el.shouldShow) continue
        const elWidth = el.offsetWidth
        const elHeight = el.offsetHeight
        const elLeft = el.offsetLeft
        const elTop = el.offsetTop

        const elCenterLeft = elLeft + elWidth / 2
        const elCenterTop = elTop + elHeight / 2

        for (let j = 0; j < len; j++) {
          if (i === j) continue
          const nextEl = this.els[j]
          if (!nextEl.shouldShow) continue

          const nextWidth = nextEl.offsetWidth
          const nextHeight = nextEl.offsetHeight
          const nextLeft = nextEl.offsetLeft
          const nextTop = nextEl.offsetTop

          const nextCenterLeft = nextLeft + nextWidth / 2
          const nextCenterTop = nextTop + nextHeight / 2

          if (
            Math.abs(nextCenterLeft - elCenterLeft) < (nextWidth + elWidth) / 2 &&
            Math.abs(nextCenterTop - elCenterTop) < (nextHeight + elHeight) / 2
          ) {
            // 碰撞了
            array[i].push(nextEl)
          }
        }
      }
      this.calCurrentShow(array)
    },
    calCurrentShow (array) {
      for (let i = 0; i < array.length; i++) {
        const el = this.els[i]
        if (el.style.display !== 'none' && array[i].length) {
          array[i].forEach(item => {
            item.style.display = 'none'
          })
        }
      }
    },
    handleHtmlLabelShow (list) {
      if (!list) return

      if (!this.els) {
        setTimeout(() => {
          this.handleHtmlLabelShow(list)
        }, 100)

        return
      }

      this.els.forEach((el) => {
        el.shouldShow = false
        const typeData = list.find((item) => item.type === el.messageType)
        if (typeData) {
          el.style.display = ''
          el.onclick = typeData.handler
          el.shouldShow = true
        } else {
          el.style.display = 'none'
          el.onclick = null
        }
      })

      this.findCollision()
    },
    updateEls () {
      this.els.forEach((el) => {
        if (el.style.display === '') {
          const scratch = new Cesium.Cartesian2()
          const position = Cesium.Cartesian3.fromDegrees(
            el.labelPosition.lng,
            el.labelPosition.lat,
            el.labelPosition.h
          )

          const canvasPosition = this.viewer.scene.cartesianToCanvasCoordinates(
            position,
            scratch
          )

          if (canvasPosition && canvasPosition.x && canvasPosition.y) {
            el.style.left = `${canvasPosition.x - el.offsetWidth / 2}px`
            el.style.top = `${canvasPosition.y - el.offsetHeight / 2 - 30}px`
          }
        }
      })
    }
  }
}
</script>

<style lang="less">
.app-container {
  width: 100%;
  height: 100%;
  background-color: #303a43;
  position: relative;
  overflow: hidden;

  .cesium-container {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
  }

  .layout-container {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    background: url("../../assets/main/bg3.png") no-repeat;
    background-size: 100% 100%;
    overflow: hidden;
    pointer-events: none;
  }

  .left-btn-con {
    width: 20px;
    height: 20px;
    position: fixed;
    top: 46.5%;
    left: 3px;
    margin: auto;
    cursor: pointer;

    img {
      width: 100%;
    }
  }

  .right-btn-con {
    width: 20px;
    height: 20px;
    position: fixed;
    top: 46.5%;
    right: 3px;
    margin: auto;
    cursor: pointer;

    img {
      width: 100%;
    }
  }

  .label-con {
    // height: 80px;
    position: fixed;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    overflow: hidden;

    p {
      height: 20px;
      display: flex;
      padding: 0 5px 1px;
      justify-content: center;
      align-items: center;
      color: white;
      margin-bottom: 10px;
    }

    .label-text1,
    .label-text3 {
      background: url("../../assets/main/25.png") no-repeat 0 0;
      background-size: 100% 100%;
    }

    p + div {
      width: 30px;
      height: 30px;
      position: relative;

      img {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
      }
    }

    .label-text3 {
      font-size: 16px;
      padding: 4px 10px;
    }

    .label-text3 + div {
      width: 50px;
      height: 50px;

      span {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        font-size: 15px;
        color: white;
        background-color: rgba(100, 100, 100, 0.3);
        border-radius: 50%;
        font-weight: bold;
        display: flex;
        justify-content: center;
        align-items: center;
      }
    }

    .label-text2-1, .label-text4 {
      background: url("../../assets/main/28.png") no-repeat 0 0;
      background-size: 100% 100%;
    }

    .label-text2-2 {
      background: url("../../assets/main/27.png") no-repeat 0 0;
      background-size: 100% 100%;
    }
  }

  .label-con:hover {
    z-index: 1;
    p {
      color: #0bc8ac;
    }
  }

  .img-change-enter-active,
  .img-change-leave-active {
    transition: opacity 0.5s ease;
  }

  .img-change-enter,
  .img-change-leave-to {
    opacity: 0;
  }
}
</style>
